package stage
{
	import edu.pku.controller.util.RegionPoint;
	import edu.pku.controller.util.SubjectDescription;
	import edu.pku.sandbox.BaseMessage;
	import edu.pku.sandbox.InvadReport;
	import edu.pku.sandbox.SensorHistoryData;
	
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.utils.Dictionary;
	import flash.utils.getTimer;
	
	import mx.collections.ArrayCollection;
	import mx.controls.Alert;
	import mx.core.Application;
	import mx.core.UIComponent;
	

	public class SandTable extends UIComponent
	{
		/**
		 * back ground color;
		 * @default
		 */
		public var backcolor:uint=0xffffff;

		//tank Dynamic
		private var tankDynamicTrack:DynamicTrack;

		//the dictionary that store all the subject
		private var allSubject:Dictionary=new Dictionary();


		//the dictionary that store all the 
		private var allTrack:Dictionary=new Dictionary();

		//the status that if the type of the subject is enable or not
		private var SensorStatus:Array=new Array();

		//background images
		private var backImage:BackgroundImage=new BackgroundImage();
		

		//the collection for the msgbox
		private var msgBoxes:ArrayCollection=new ArrayCollection();

		//rfid box;
		//private var rfidbox:MsgBox=new MsgBox();

		//target box;
		//private var targetbox:MsgBox=new MsgBox();
		
		private var rfidReadedStamp:uint=0;
		
		/**
		 * the intrade arrow
		 * @default 
		 */
		private var intradeArrow:ArrowSprite=new ArrowSprite();
		
		/**
		 * the retreate arrow
		 * @default 
		 */
		private var retreateArrow:ArrowSprite=new ArrowSprite();
		
		
		public function showIntradeArrow(visible:Boolean):void
		{
			intradeArrow.visible=visible;	
		}
		
		public function showRetrateArrow(visible:Boolean):void
		{
			retreateArrow.visible=visible;
		}
		
		private function setIntradeArrowPosition():void
		{
			intradeArrow.visible=false;
			intradeArrow.x=90;
			intradeArrow.y=480;
			intradeArrow.rotation=-30;
			myAddChild(intradeArrow);
		}
		
		private function setRetrateArrowPosition():void
		{
			retreateArrow.visible=false;
			retreateArrow.x=190;
			retreateArrow.y=400;
			retreateArrow.rotation=-210;
			myAddChild(retreateArrow);
		}

		
		private function hideAllSensroType():void
		{
			SensorStatus[AppConstant.TYPE_INFRARED_SENSOR]=false;
			SensorStatus[AppConstant.TYPE_METAL_SENSOR]=false;
			SensorStatus[AppConstant.TYPE_RFID_READER]=false;
			SensorStatus[AppConstant.TYPE_PRESSURE_SENSOR]=false;
			SensorStatus[AppConstant.TYPE_SOUND_SENSOR]=false;
		}

		private function hideTank():void
		{
			var tankObj:Object=allSubject['TANK'];
			if (tankObj)
			{
				var tank:SandTableSubject=tankObj as SandTableSubject;
				tank.visible=false;
			}
		}

		private function showTank():void
		{
			var tankObj:Object=allSubject['TANK'];
			trace("tankObj==null?="+(tankObj==null));
			if (tankObj)
			{
				var tank:SandTableSubject=tankObj as SandTableSubject;
				tank.visible=true;
			}
		}

		/**
		 * this function is to be called by SerivceArrange UI
		 */
		public function clearScenario():void
		{
			clearSensorTracks();
			removeAllSensorSubject();
			clearTankTrack();
			hideTank();
			showIntradeArrow(false);
			showRetrateArrow(false);
			var blank_str:String="    ";
			Application.application.clearMsgbox();
			IdentifiedTank=false;
			addedSprite.removeAll();
			rfidreaded=false;
		}

		private var IdentifiedTank:Boolean=false;
		
		private function clearTankTrack():void
		{
			if (contains(tankDynamicTrack))
				removeChild(tankDynamicTrack);
			tankDynamicTrack=new DynamicTrack();
			myAddChild(tankDynamicTrack);
		}

		/**
		 * clear tracks of sensors
		 */
		private function clearSensorTracks():void
		{
			for (var key:Object in allTrack)
			{
				var object:DynamicTrack=allTrack[key] as DynamicTrack;
				allTrack[key]=null;
				if (object != null && contains(object))
					removeChild(object);
			}
		}

		public function SandTable(width:int, height:int)
		{
			super();
			trace("init_sand_table:"+ this.width + " " + this.height);
			this.width=width;
			this.height=height;
			tankDynamicTrack=new DynamicTrack();
			myAddChild(backImage);
			myAddChild(tankDynamicTrack);
			setIntradeArrowPosition();
			setRetrateArrowPosition();
			trace("end_init_sand_table");
		}


		/**
		 * clear all the current tracks
		 * 
		 */
		public function clearAllCurrentTrack():void
		{
			tankDynamicTrack.clearTrack();
			//clear all sensor track
			for (var key:Object in allTrack)
			{
				var object:DynamicTrack=allTrack[key] as DynamicTrack;
				if (object != null)
				{
					object.clearTrack();
				}
			}
		}
		
//InforBox part=====================
//		public function setRfidInfo(msg:String):void
//		{
//			rfidbox.textValue=msg;
//		}
//
//		public function setTargetInfo(msg:String):void
//		{
//			targetbox.textValue=msg;
//		}
//
//		public function showRfidBox():void
//		{
//			PopUpManager.removePopUp(rfidbox);
//			PopUpManager.addPopUp(rfidbox, this, false);
//			if (!msgBoxes.contains(rfidbox))
//				msgBoxes.addItem(rfidbox);
//			repositionInfoVBox();
//		}
//
//		public function hideRfidBox():void
//		{
//			PopUpManager.removePopUp(rfidbox);
//			var index:int=msgBoxes.getItemIndex(rfidbox);
//			if (index >= 0)
//			{
//				msgBoxes.removeItemAt(index);
//			}
//			repositionInfoVBox();
//		}
//
//
//		public function showTargeBox():void
//		{
//			PopUpManager.removePopUp(targetbox);
//			PopUpManager.addPopUp(targetbox, this, false);
//			if (!msgBoxes.contains(targetbox))
//				msgBoxes.addItem(targetbox);
//			repositionInfoVBox();
//		}
//
//		public function hideTargetBox():void
//		{
//			PopUpManager.removePopUp(targetbox);
//			var index:int=msgBoxes.getItemIndex(targetbox);
//			if (index >= 0)
//			{
//				msgBoxes.removeItemAt(index);
//			}
//			repositionInfoVBox();
//		}
//
//		public function repositionInfoVBox():void
//		{
//			var currentWidth:int=this.height;
//
//			for each (var item:MsgBox in msgBoxes)
//			{
//				item.x=this.x + this.width - item.width;
//				item.y=this.y + currentWidth - item.height;
//				currentWidth-=item.height;
//			}
//		}

//end info box========================================================

		public function sandtableResize(inwidth:int, inheight:int):void
		{
			width=inwidth;
			height=inheight;
		}

		/**
		 * Add a subject to the sandtable with id and position
		 * @param id
		 * @param x
		 * @param y
		 */
		public function addSubjectByDescription(subdes:SubjectDescription):void
		{
			var sprite:Sprite=SandTableSubject.createSubjectByDescription(subdes);
			//add the sprite to the allSubject
			//trace("subdes.type:"+subdes.type+ "  sudes.id:"+subdes.id);
			this.allSubject[subdes.id]=sprite;
			
			if(subdes.id=="TANK")
			{
				sprite.visible=false;
				myAddChild(sprite);
			}
		}

		private var rfidreaded:Boolean=false;
		
		private function convertRfidString(rfidstr:String):String
		{
			var rfidstrs:Array=rfidstr.split("#");
			return ResourceManager.MSG_READ_RFID_INFORMATION+rfidstrs[0].toString(); 
			//return "RFID标签:"+rfidstrs[0].toString()+"\r\n"+"物体:"+rfidstrs[1].toString();
		}
		
		private var friendEntered:Boolean=false;
		
		private function checkFriendTarget():Boolean
		{
			var timeInteval:int=2000;
			if(friendEntered)
			{
				friendEntered=false;
				return true;
			}
			//now is less than rfid time
			if (flash.utils.getTimer()-rfidReadedStamp<timeInteval)
			{
				friendEntered=true;
				return true;
			}
			else
			{
				return false;
			}
		}
		
		public function updateMessage(msg:BaseMessage):Boolean
		{
			//trace("msg.type : " + msg.type);
			//trace("msg.id : " + msg.id);
			if(msg.type==AppConstant.TYPE_SENSOR_MESSAGE || msg.type==AppConstant.TYPE_COMBINATION || msg.type==AppConstant.TYPE_RFID_MESSAGE)
			{
				var subject:SandTableSubject=allSubject[msg.id] as SandTableSubject;
				if (subject == null)
					return false;
				if (msg.type == AppConstant.TYPE_SENSOR_MESSAGE)
				{
					var data:SensorHistoryData=msg.value as SensorHistoryData;
					subject.updateData(data);
				}
				else if (msg.type == AppConstant.TYPE_RFID_MESSAGE)
				{
					//rfid message arrived
					var rfidstr:String=msg.value as String;
					var rfidsubject:RfidReaderSubject=subject as RfidReaderSubject;
					rfidsubject.updateRfidInfo(rfidstr);
					rfidReadedStamp=flash.utils.getTimer();
					if(!rfidreaded)
					{
						Application.application.setInforBoxMessage(convertRfidString(rfidstr));
						rfidreaded=true;
					}
					//setRfidInfo();
				}
				//combine track or sensor track
				else if (msg.type == AppConstant.TYPE_COMBINATION)
				{
					trace("receive combination");
					//if have combination position we show the Tank
					showTank();
					var point:RegionPoint=msg.value as RegionPoint;
					if (point)
					{
						subject.x=point.x - subject.width / 2;
						subject.y=point.y - subject.height / 2;
						if(tankDynamicTrack.getPointCount()==0)
						{
							var combinedSensorNames:String=ResourceManager.getCombinedInfo(addedSprite);
							Application.application.setInforBoxMessage("<font color='red'>"+combinedSensorNames+"</font>"+"共同生成轨迹……");		
						}
						tankDynamicTrack.addPoint(point);
						trace(tankDynamicTrack.arrayPoints.length);
					}
					else
					{
						trace("Error:can't convert to LocationMessage");
					}
				}
			}
			//here we treat the 
			else if(msg.type==AppConstant.TYPE_INFRARED_MESSAGE)
			{
				var invadeReport:InvadReport=msg.value as InvadReport;
				if(invadeReport.type==AppConstant.TYPE_INVADE)
				{
					trace("receive_intrade");
//					if(checkFriendTarget())
//					{
//						showIntradeArrow(true);
//						Application.application.setInforBoxMessage("我方目标进入检测区域！");
//					}
//					else
//					{
//						showIntradeArrow(true);
//						Application.application.setInforBoxMessage("红外传感器发现物体入侵！");
//					}
						if(!intradeArrow.visible)
						{
							showRetrateArrow(false);
							showIntradeArrow(true);
							Application.application.setInforBoxMessage(ResourceManager.MSG_SUBJECT_INTRADE);
							if(!IdentifiedTank)
							{
								IdentifiedTank=true;
								Application.application.setInforBoxMessage(ResourceManager.MSG_IDENTYFY_AS_TANK);
							}
						}
						
				}
				else if(invadeReport.type==AppConstant.TYPE_RETREAT)
				{
					trace("receive_retreate");
//					if(checkFriendTarget())
//					{
//						showRetrateArrow(true);
//						Application.application.setInforBoxMessage("我方目标撤离检测区域！");
//					}
//					else
//					{
//						showRetrateArrow(true);
//						Application.application.setInforBoxMessage("敌方目标撤离检测区域！");
//					}
					if(!retreateArrow.visible)
					{
						showIntradeArrow(false);
						showRetrateArrow(true);
						Application.application.setInforBoxMessage(ResourceManager.MSG_ENEMY_TANK_LEAVE);
					}
				}
				//else if(invadeReport.type==AppConstant.
			}
			else //other type of track
			{
				var typestr:String=msg.type.toString();
				var trackobj:Object=allTrack[typestr];
				point=msg.value as RegionPoint;
				trace("receive sensor track");
				var dtrack:DynamicTrack=null;
				var sensorName:String=null
				if (trackobj)
				{
					//trace("update sensor track");
					dtrack=trackobj as DynamicTrack;
					if(!dtrack.messageShowed())
					{
						sensorName=ResourceManager.getSensorLabel(msg.type);
						Application.application.setInforBoxMessage("<font color='red'>"+sensorName+"</font>"+"生成轨迹……");		
					}
					dtrack.addPoint(point);
				}
				else
				{
					//trace("add sensor track");	
					dtrack=new DynamicTrack();
					dtrack.setDrawColor(getTrackColorByType(msg.type));
					if(!dtrack.messageShowed())
					{
						sensorName=ResourceManager.getSensorLabel(msg.type);
						Application.application.setInforBoxMessage("<font color='red'>"+sensorName+"</font>"+"生成轨迹……");		
					}
					dtrack.addPoint(point);
					allTrack[typestr]=dtrack;
					myAddChild(dtrack);
				}
			}
			return true;
		}


		/**
		 * get track draw color by type
		 * @param type
		 */
		private function getTrackColorByType(type:int):uint
		{
			if (type == AppConstant.TYPE_PRESSURE_SENSOR)
			{
				return AppConstant.COLOR_PRESSURE_TRACK;
			}
			else if (type == AppConstant.TYPE_INFRARED_SENSOR)
			{
				return AppConstant.COLOR_INFRARED_TRACK;
			}
			else if (type == AppConstant.TYPE_METAL_SENSOR)
			{
				return AppConstant.COLOR_METAL_TRACK;
			}
			else if (type == AppConstant.TYPE_SOUND_SENSOR)
			{
				return AppConstant.COLOR_SOUND_TRACK;
			}
			else if(type==AppConstant.TYPE_VIBRATE_SENSOR)
			{
				return AppConstant.COLOR_VIBRATE_TRACK;
			}
			else
				return AppConstant.COLOR_BLUE;
		}

		public function addEventListenerById(id:String, event:String, listener:Function):void
		{
			var sp:Sprite=this.allSubject[id];
			if (sp == null)
				return;
			sp.addEventListener(event, listener);
		}

		public function test(event:Event):void
		{
			Alert.show("hello");
		}

		/**
		 * draw the background using background or back image
		 * @param unscaledWidth
		 * @param unscaledHeight
		 */
		protected function drawBackGround(unscaledWidth:Number, unscaledHeight:Number):void
		{
			drawBG(unscaledWidth, unscaledHeight);
		}

		public function drawBG(unscaledWidth:Number, unscaledHeight:Number):void
		{
			graphics.clear();

//			var imgDisplay:DisplayObject=new ResourceManager.SandTableBackground() as DisplayObject;
//			var bm:BitmapData=GraphicsResource.createAlphaBitmapData(imgDisplay);
//			graphics.beginBitmapFill(bm, null, false, true);
			graphics.lineStyle(1);
			graphics.beginFill(backcolor);
			graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
			graphics.endFill();
		}

		/**
		 * draw the
		 * @param unscaledWidth
		 * @param unscaledHeight
		 */
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			drawBackGround(unscaledWidth, unscaledHeight);
			//addTypeToSprite();
		}


		private  var addedSprite:ArrayCollection=new ArrayCollection();
		/**
		 * this used to drag and drop the base service to the sandtable
		 *
		 * @param type
		 */
		public function addTypeToSprite(type:int):void
		{
			addedSprite.addItem(type);
			for (var id:String in allSubject)
			{
				var subject:SandTableSubject=allSubject[id] as SandTableSubject;
				if (subject.type == type)
				{
					myAddChild(subject);
				}
			}
		}

		/**
		 * remove types of sensor in the inType and in the allSubject
		 */
		private function removeAllSensorSubject():void
		{
			var i:int=0;
			for each (var subject:SandTableSubject in allSubject)
			{
				//trace("subject type:"+subject.type+"contain(subject):"+contains(subject));
				//
				if (contains(subject) && inType(subject.type))
				{
					subject.clearHistoryRecords();
					removeChild(subject);
					i+=1;
				}
			}
			//trace("remove_object_number:"+i);
		}

		private function inType(type:int):Boolean
		{
			//trace("=========intype============"+type);
			var rst:Boolean=([AppConstant.TYPE_INFRARED_SENSOR, AppConstant.TYPE_RFID_READER, AppConstant.TYPE_PRESSURE_SENSOR, AppConstant.TYPE_SOUND_SENSOR, AppConstant.TYPE_METAL_SENSOR,AppConstant.TYPE_VIBRATE_SENSOR].indexOf(type) >= 0);
			//trace("=========intype==========type:"+type+" rst:"+rst);
			return rst;
		}

		/**
		 * here we control the layer of the subject
		 * @param obj
		 */
		private function myAddChild(obj:DisplayObject):void
		{
			//addChild(obj);
			var sprite:OrderSprite=obj as OrderSprite;
			if (sprite != null)
			{
				if (this.numChildren == 0)
				{
					addChild(sprite);
					return;
				}
				for (var i:int=0; i < this.numChildren; i++)
				{
					var item:OrderSprite=getChildAt(i) as OrderSprite;
					if (item == null)
						continue;
					if (sprite.displayOrder < item.displayOrder)
					{
						addChildAt(sprite, i);
						return;
					}
				}
				addChild(sprite);
			}
			else
			{
				trace("Error:no order component!");
					//addChild(obj);
			}

		}
	}
}